package com.wing.file.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.exception.CosClientException;
import com.qcloud.cos.exception.CosServiceException;
import com.qcloud.cos.model.*;
import com.qcloud.cos.utils.IOUtils;
import com.wing.common.exception.BusinessException;
import com.wing.file.model.response.FileVO;
import com.wing.file.service.AbstractService;
import com.wing.file.service.TengXunFileService;
import com.wing.file.util.FileType;
import com.wing.file.util.TengXunFileUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.time.ZoneId;
import java.util.*;

/**
 * 腾讯 文件上传服务类
 */
@Service("tengXunFileServiceImpl")
@Slf4j
public class TengXunFileServiceImpl implements TengXunFileService {

    @Autowired
    private TengXunFileUtil tengXunFileUtil;


    @Value("${file.tengxun.system.domainName}")
    private String sysDomainName;


    @Value("${file.tengxun.product.domainName}")
    private String prodDomainName;


    private final static String SYSTEM_BUCKET_NAME = "system-1332443484";

    private final static String TK_BUCKET_NAME = "product-1332443484";

    @Override
    public FileVO uploadFile(MultipartFile file, String path) throws Exception {
        COSClient cosClient = tengXunFileUtil.getCosClient();
        String key = "";
        if (StringUtils.isNotBlank(path)) {
            key = path + UUID.randomUUID().toString() + "_" + file.getOriginalFilename();
        } else {
            key = UUID.randomUUID().toString() + "_" + file.getOriginalFilename();
        }

        //String localPath = file.getOriginalFilename();

        ObjectMetadata objectMetadata = new ObjectMetadata();
        //objectMetadata.setHeader("expires", new Date(1660000000000L));

        String filename = file.getOriginalFilename().toLowerCase();
        if (!filename.endsWith(".pdf")) {
            objectMetadata.setHeader("Content-Type", "text/html");
        }
        if (filename.endsWith(".apk")) {
            objectMetadata.setHeader("Content-Disposition", "attachment");
        }
        if (filename.endsWith(".png") || filename.endsWith(".jpeg") || filename.endsWith(".jpg")) {
            objectMetadata.setHeader("Content-Type", "image/jpeg");
        }

        PutObjectRequest putObjectRequest = new PutObjectRequest(SYSTEM_BUCKET_NAME, key, multipartFileToFile(file));
        putObjectRequest.withMetadata(objectMetadata);

        PutObjectResult putObjectResult = cosClient.putObject(putObjectRequest);

        cosClient.shutdown();

        if (null != putObjectResult && StringUtils.isNotBlank(putObjectResult.getRequestId())) {
            FileVO fileVO = new FileVO();
            fileVO.setUrl("https://" + sysDomainName + "/" + key);
            fileVO.setSmUrl("https://" + sysDomainName + "/" + key);
            fileVO.setSrc("https://" + sysDomainName + "/" + key);
            fileVO.setFileName(file.getOriginalFilename());
            return fileVO;
        } else {
            throw new BusinessException("上传失败");
        }
    }

    @Override
    public FileType getFileType() {
        return FileType.TENGXUN;
    }

    @Override
    public void downloadFile(String fileUrl, HttpServletResponse response) throws Exception{
        COSClient cosClient = tengXunFileUtil.getCosClient();

        int firstSlashIndex = fileUrl.indexOf("/");
        String result = "";
        String fileName = "";
        if (firstSlashIndex != -1) {
            int index = fileUrl.indexOf("/", fileUrl.indexOf("//") + 2);

            if (index != -1 && index + 1 < fileUrl.length()) {
                result = fileUrl.substring(index + 1);
            }

            int lastSlashIndex = fileUrl.lastIndexOf("/");
            if (lastSlashIndex != -1 && lastSlashIndex + 1 < fileUrl.length()) {
                fileName = fileUrl.substring(lastSlashIndex + 1);
            }
        }
        GetObjectRequest getObjectRequest = new GetObjectRequest(SYSTEM_BUCKET_NAME, result);
        InputStream cosObjectInput = null;
        try {
            response.setContentType("application/octet-stream");
            //设置响应头
            response.setHeader("Content-Disposition",
                    "attachment;filename=" + URLEncoder.encode(fileName,
                            "UTF-8"));
            COSObject cosObject = cosClient.getObject(getObjectRequest);
            //拿到输入流
            cosObjectInput = cosObject.getObjectContent();
            BufferedInputStream buffInputStream = new BufferedInputStream(cosObjectInput, 1024 * 10);
            //设置文件大小
            byte buf[] = new byte[1024*10];
            int length;
            OutputStream outputStream = response.getOutputStream();
            while ((length = buffInputStream.read(buf,0,1024*10)) != -1) {
                outputStream.write(buf, 0, length);
            }
            response.setContentLength(length);
            response.flushBuffer();
            //关闭流
            buffInputStream.close();
            cosObjectInput.close();
            outputStream.close();
            log.info("文件导出:"+fileUrl);
        } catch (CosClientException e) {
            e.printStackTrace();
        } finally {
            cosClient.shutdown();
        }

        // 处理下载到的流
        // 这里是直接读取，按实际情况来处理
//        byte[] bytes = null;
//        try {
//            bytes = IOUtils.toByteArray(cosObjectInput);
//        } catch (IOException e) {
//            e.printStackTrace();
//        } finally {
//            // 用完流之后一定要调用 close()
//            cosObjectInput.close();
//        }

        // 在流没有处理完之前，不能关闭 cosClient
        // 确认本进程不再使用 cosClient 实例之后，关闭即可

    }

    /**
     * 批量上传
     * @param files
     * @param path
     * @return
     * @throws Exception
     */
    @Override
    public List<FileVO> uploadMultipartFile(MultipartFile[] files, String path) throws Exception {
        COSClient cosClient = tengXunFileUtil.getCosClient();
        List<FileVO> list = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(Arrays.asList(files))) {
            for (MultipartFile file : files) {
                String key = "";
                if (StringUtils.isNotBlank(path)) {
                    key = path + UUID.randomUUID().toString() + "_" + file.getOriginalFilename();
                } else {
                    key = UUID.randomUUID().toString() + "_" + file.getOriginalFilename();
                }
                ObjectMetadata objectMetadata = new ObjectMetadata();

                String filename = Objects.requireNonNull(file.getOriginalFilename()).toLowerCase();
                if (!filename.endsWith(".pdf")) {
                    objectMetadata.setHeader("Content-Type", "text/html");
                }
                if (filename.endsWith(".apk")) {
                    objectMetadata.setHeader("Content-Disposition", "attachment");
                }
                if (filename.endsWith(".png") || filename.endsWith(".jpeg") || filename.endsWith(".jpg")) {
                    objectMetadata.setHeader("Content-Type", "image/jpeg");
                }

                PutObjectRequest putObjectRequest = new PutObjectRequest(SYSTEM_BUCKET_NAME, key, multipartFileToFile(file));
                putObjectRequest.withMetadata(objectMetadata);

                PutObjectResult putObjectResult = cosClient.putObject(putObjectRequest);

                cosClient.shutdown();

                if (null != putObjectResult && StringUtils.isNotBlank(putObjectResult.getRequestId())) {
                    FileVO fileVO = new FileVO();
                    fileVO.setUrl("https://" + sysDomainName + "/" + key);
                    fileVO.setSmUrl("https://" + sysDomainName + "/" + key);
                    fileVO.setSrc("https://" + sysDomainName + "/" + key);
                    fileVO.setFileName(file.getOriginalFilename());
                    list.add(fileVO);
                }
            }
        }
        return list;
    }

    /**
     * 获取文件夹中的文件
     * @param path 文件夹路径 your/folder/
     * @return
     * @throws Exception
     */
    @Override
    public List<FileVO> listObjects(String path) throws Exception {
        //获取云服务器客户端
        COSClient cosClient = tengXunFileUtil.getCosClient();
        List<FileVO> list = new ArrayList<>();
        try {
            // 3. 获取指定文件夹中的文件列表
            ListObjectsRequest listObjectsRequest = new ListObjectsRequest()
                    // 存储桶名称
                    .withBucketName(TK_BUCKET_NAME)
                    // 指定文件夹前缀
                    .withPrefix(path)
                    // 使用斜杠作为分隔符，确保只列出文件夹内的文件
                    .withDelimiter("/");

            // 4. 获取文件列表
            ObjectListing objectListing = cosClient.listObjects(listObjectsRequest);
            List<COSObjectSummary> objectSummaries = objectListing.getObjectSummaries();
            if (!objectSummaries.isEmpty()) {
                // 5. 输出文件列表
                for (COSObjectSummary objectSummary : objectSummaries) {
                    if (objectSummary.getSize()>0){
                        FileVO fileVO = new FileVO();
                        fileVO.setUrl("https://" + prodDomainName + "/" + objectSummary.getKey());
                        fileVO.setModifiedTime(objectSummary.getLastModified().toInstant()
                                .atZone(ZoneId.systemDefault())
                                .toLocalDateTime());
                        fileVO.setSrc(objectSummary.getKey());

                        // 查找最后一个斜杠的位置
                        int lastIndex = objectSummary.getKey().lastIndexOf("/");
                        // 使用 substring 截取文件名
                        String fileName = objectSummary.getKey().substring(lastIndex + 1);
                        fileVO.setFileName(fileName);
                        list.add(fileVO);
                    }
                }
            }
            return list;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 6. 关闭 COSClient
            cosClient.shutdown();
        }
        return null;
    }


    /**
     * 将MultipartFile转换为File
     *
     * @param multiFile
     * @return
     */
    public static File multipartFileToFile(MultipartFile multiFile) {
        // 获取文件名
        String fileName = multiFile.getOriginalFilename();
        // 获取文件后缀
        String prefix = fileName.substring(fileName.lastIndexOf("."));
        // 若须要防止生成的临时文件重复,能够在文件名后添加随机码

        try {
            File file = File.createTempFile(fileName, prefix);
            multiFile.transferTo(file);
            return file;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


}
